<template>
  <div class="form-item-group" :style="{ '--label-width': labelWidth }">
    <template v-for="(row, prop) in formData">
      <el-divider content-position="left" :key="prop" v-if="row.hasHeadDivider">
        {{ row.headDividerTitle }}
      </el-divider>
      <el-form-item
        :style="{
          width: row.hideLabel ? '100%' : row.width ? row.width : '100%',
          paddingRight: row.rightGap ? row.rightGap : '0',
          paddingLeft: row.leftGap ? row.leftGap : '0'
        }"
        :key="prop"
        v-if="!row.hidden"
        class="form-item"
        :class="{
          'is-required': row.required && editMode !== 'detail',
          'hide-label': row.hideLabel
        }"
      >
        <span
          slot="label"
          :class="{
            'label-painter': row.required !== true && editMode !== 'detail'
          }"
        >
          {{ row.hideLabel ? '' : row.label }}
        </span>
        <template>
          <el-divider
            content-position="left"
            v-if="row.type === 'divider'"
            class="custom-divider"
          >
            {{ row.dividerTitle }}
          </el-divider>
          <template v-else-if="row.type === ':slot'">
            <slot :name="row.slot || prop"></slot>
          </template>
          <template v-else-if="row.type === 'async-select'">
            <async-select
              v-model="row.value"
              :disabled="
                typeof row.disabled === 'undefined'
                  ? editMode === 'detail'
                  : row.disabled
              "
              :filterable="row.filterable"
              :placeholder="row.placeholder"
              :clearable="row.clearable"
              :default-dropdown-options="row.options"
              :option-mapping="row.optionMapping"
              :api-params="row.apiParams"
              :edit-mode="editMode"
              :api="row.api"
              :field-name="prop"
              :form-data="formData"
              :dependencies="row.dependencies"
              @change="change($event, row, prop)"
            ></async-select>
          </template>
          <template v-else-if="row.type === 'select' && row.schema">
            <schema-select
              v-model="row.value"
              class="form-item-input"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :schema="row.schema"
              :clearable="row.clearable"
              :filterable="true"
              :placeholder="row.placeholder"
              @change="change($event, row)"
            ></schema-select>
          </template>
          <template v-else-if="row.type === 'tree-select' && row.remote">
            <tree-select
              v-model="row.value"
              :options="selectOptions[row.remote.list + '-tree']"
              :props="{
                label: row.remote.label,
                value: row.remote.value
              }"
              @change="change($event, row)"
              :filterable="row.filterable"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
            ></tree-select>
          </template>
          <template v-else-if="row.type === 'select' && row.remote">
            <el-select
              v-model="row.value"
              class="form-item-input"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :placeholder="row.placeholder || '请选择'"
              @change="change($event, row, prop)"
              @visible-change="onVisibleChange($event, row, prop)"
              :no-data-text="row.noDataText"
              :filterable="true"
            >
              <el-option
                v-for="(op, index) in row.condition
                  ? selectOptions.$condition[prop] ||
                    selectOptions[row.remote.list]
                  : selectOptions[row.remote.list]"
                :key="index"
                :label="op[row.remote.label]"
                :value="op[row.remote.value]"
              />
            </el-select>
          </template>
          <template v-else-if="row.type === 'select' && row.dictKey">
            <dict-select
              v-model="row.value"
              class="form-item-input"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :dict-key="row.dictKey"
              :filterable="row.filterable"
              :placeholder="row.placeholder || '请选择'"
              @change="change($event, row)"
            ></dict-select>
          </template>
          <template slot-scope v-else-if="row.type === 'select' && row.options">
            <el-select
              v-model="row.value"
              class="form-item-input"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :filterable="row.filterable"
              :multiple="row.multiple"
              :placeholder="row.placeholder || '请选择'"
              @change="change($event, row, prop)"
            >
              <el-option
                v-for="op in row.options"
                :key="op.key"
                :label="op.label"
                :value="op.value"
              />
            </el-select>
          </template>
          <template slot-scope v-else-if="row.type === 'cascader'">
            <!-- <el-cascader v-model="row.value" class="form-item-input"
              :disabled="(editMode === 'detail') ? true : (!!row.disabled)" :show-all-levels="row.showLevels||false"
              :options="row.options"
              :props="row.props" :placeholder="row.placeholder" @change="change($event, row, prop)">
            </el-cascader> -->
            <tree-cascade
              v-model="row.value"
              class="form-item-input"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :show-all-levels="row.showLevels || false"
              :options="
                row.options
                  ? row.options
                  : selectOptions[row.remote.list + '-tree']
              "
              :props="row.props"
              :placeholder="row.placeholder"
              :filterable="row.filterable"
              @change="change($event, row, prop)"
            ></tree-cascade>
          </template>
          <template
            v-else-if="row.type === 'radio' && (row.dictKey || row.options)"
          >
            <dict-radio
              v-model="row.value"
              class="form-item-input"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :dict-key="row.dictKey"
              :options="row.options"
              @change="change($event, row, prop)"
            ></dict-radio>
          </template>
          <template v-else-if="row.type === 'switch'">
            <el-switch
              v-model="row.value"
              class="form-item-input"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              active-color="#0D48CE"
              inactive-color="#DCDFE6"
              :active-value="1"
              :inactive-value="0"
              :active-text="(row.text || [])[0]"
              :inactive-text="(row.text || [])[1]"
              @change="change($event, row, prop)"
            ></el-switch>
          </template>
          <template
            v-else-if="row.type === 'data-picker' || row.type === 'date-picker'"
          >
            <el-date-picker
              v-model="row.value"
              class="form-item-input"
              :type="row.pickerType || 'date'"
              :value-format="row.valueFormat ? row.valueFormat : 'yyyy-MM-dd'"
              range-separator="~"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              placeholder="选择日期"
              start-placeholder="选择起始日期"
              end-placeholder="选择终止日期"
              @input="change($event, row)"
              @change="change($event, row)"
            ></el-date-picker>
          </template>
          <template v-else-if="row.type === 'time-picker'">
            <el-time-picker
              v-model="row.value"
              class="form-item-input"
              value-format="HH:mm:ss"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :placeholder="
                row.placeholder == null ? 选择时间 : row.placeholder
              "
              @change="change($event, row)"
            ></el-time-picker>
          </template>
          <template v-else-if="row.type === 'number'">
            <el-input-number
              v-model="row.value"
              class="form-item-input"
              :placeholder="row.placeholder"
              controls-position="right"
              :controls="row.showControls"
              :min="typeof row.min === 'undefined' ? 0 : row.min"
              :max="typeof row.max === 'undefined' ? Infinity : row.max"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :step="row.step"
              :precision="row.precision"
              :step-strictly="row.stepStrictly"
              @change="change($event, row)"
            />
          </template>
          <template v-else-if="row.type === 'citys'">
            <CitySelect
              :placeholder="row.placeholder"
              class="form-item-input"
              v-model="row.value"
              @change="change($event, row, prop)"
              :jumpable="
                typeof row.jumpable === 'undefined' ? true : row.jumpable
              "
              :disabled="editMode === 'detail' ? true : !!row.disabled"
            ></CitySelect>
          </template>
          <!-- 增加文件上传类型 -->
          <template v-else-if="row.type === 'upload'">
            <CImgUploadNew
              :actionUrl="row.actionUrl"
              :parameters="row.uploadParas"
              @uploadSuccess="row.handleSuccess"
              :beforeUpload="row.beforeFileUpload"
              @remove="row.handleRemove"
            ></CImgUploadNew>
          </template>

          <template v-else-if="row.type === 'singleImgUpload'">
            <CImgUploadNew
              :editMode="editMode"
              class="singleImgUpload"
              :initList="[{ fileUrl: row.value }]"
              :actionUrl="row.actionUrl"
              :uploadParas="{ type: 'image', fileNum: 1 }"
              @uploadSuccess="onSingleImgUpload(prop, $event)"
              :beforeUpload="row.beforeFileUpload"
              @remove="onSingleImgRemove(prop, $event)"
            ></CImgUploadNew>
          </template>
          <template v-else-if="row.type === 'imgListUpload'">
            <CImgUploadNew
              :editMode="editMode"
              class="imgListUpload"
              :initList="
                row.value && !Array.isArray(row.value)
                  ? row.value
                      .split(',')
                      .filter(i => i)
                      .map(i => ({ fileUrl: i }))
                  : []
              "
              :actionUrl="row.actionUrl"
              :uploadParas="{ type: 'image', fileNum: row.num }"
              @uploadSuccess="onImgListUpload(prop, $event)"
              :beforeUpload="row.beforeFileUpload"
              @remove="onImgListRemove(prop, $event)"
            ></CImgUploadNew>
          </template>
          <!-- <template v-else-if="row.type === 'coordinates'">
            <Coordinates
              v-model="row.value"
              :init-search-field="row.initSearchField"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
            ></Coordinates>
          </template> -->
          <template v-else-if="row.type === 'uploadFormItem'">
            <UploadFormItem
              :editMode="editMode"
              v-model="row.value"
              :actionUrl="row.actionUrl"
            ></UploadFormItem>
          </template>
          <template v-else-if="row.type === 'CFileUpload'">
            <CFileUpload
              :editMode="editMode"
              v-model="row.value"
              :actionUrl="row.actionUrl"
              :tipLabel="row.tipLabel"
            ></CFileUpload>
          </template>
          <template v-else-if="row.type === 'CFileUploadList'">
            <CFileUploadList
              :editMode="editMode"
              v-model="row.value"
              :actionUrl="row.actionUrl"
              :tipLabel="row.tipLabel"
            ></CFileUploadList>
          </template>
          <template slot-scope v-else>
            <el-input
              v-model="row.value"
              class="form-item-input"
              :type="row.type"
              :disabled="editMode === 'detail' ? true : !!row.disabled"
              :placeholder="row.placeholder"
              :maxlength="row.maxlength || (row.type === 'textarea' ? 100 : 36)"
              resize="none"
              @input="change($event, row)"
              :rows="row.rows || 3"
              show-word-limit
              @change="change($event, row)"
            />
          </template>
          <div class="form-item-explain" v-if="!!row.explainTxt">
            {{ row.explainTxt }}
          </div>
          <div class="el-form-item__error" v-if="startCheck">
            {{ row.customError }}
          </div>
        </template>
      </el-form-item>
    </template>
  </div>
</template>

<script>
/**
 *form-item 列表，根据配置，显示form-item输入框，用于添加、编辑对话框中内容输入，支持非空校验
 * 输入参数，使用对象形式，key为api参数名
 * formData = { "param": {label: '名称', value: '', required: true}, }
 * 参数：
 * label: 显示名称
 * value: 输入值
 * type：输入框类型，默认text，支持：select、date-picker、time-picker、switch、number
 *
 *      类型 async-select 异步下拉框(支持字段间依赖) 用法：
 *
 *      import { list as buildingListRaw } from "@/api/elevator-archives/configuration/building.js";
 *      import { list as estateListRaw } from "@/api/elevator-archives/configuration/housingMgt.js";
 *
 *      this.formData = {
 *        estateId: { label: '安装小区', required: true, value: '', width:'50%', rightGap: '10px', type:'async-select', api:estateListRaw },
 *        buildingId: { label: '安装楼栋', required: true, value: '', width: '50%', leftGap: '10px', type:'async-select', api:buildingListRaw, dependencies:['estateId']}, // dependencies 数组接收依赖的其他字段名
 *      ...}
 *
 *      同时需要为使用 async-select 的字段增加change事件
 *      methods: {
 *        change(data) {
 *          ...
 *          this.asyncSelectListener(this.formData, data);
 *          ...
 *        }
 *        以上使用detail_mixin 方法：this.asyncSelectListener(this.formData, data)
 *
 *        或者：
 *        change(data) {
 *          if (data && data.prop === 'estateId') {
 *            this.$set(this.formData.estateId, 'value', data.value);
 *          }
 *
 *          if (data && data.prop === 'buildingId') {
 *            this.$set(this.formData.buildingId, 'value', data.value);
 *          }
 *        }
 *
 *      使用参考 src\views\elevator-archives\configuration\equipments\components\ItemDetail.vue
 *
 * dictKey：数据字典名称，type为select时，传入dictKey使用数据字典下拉选择框
 * pickerType: 日期选择类型，type=date-picker时有效，支持类型见elementUI
 * required: true-必填项
 * filterable、placeholder、multiple、disabled，透传至elementUI
 * explainTxt: 输入校验失败是显示提示文字，默认为：请输入{标签名}
 * width: '50%' 非必填，输入百分比的字符串，代表一个字段在一行中占有的宽度，不填就是100%
 * leftGap: '10px' 非必填，输入字符串宽度，代表字段左侧留白间距，此间距包含在上面的width中
 * rightGap: '10px' 同上，右侧留白间距
 * hasHeadDivider: false, 默认false, 非必填，为true则设置一个el-divider的分割线
 * headDividerTitle: '标题' 非必填，分割线的标题名称
 *
 * @checkValue：触发输入校验，校验成功返回{key:value}形式对象，可直接用于数据提交
 *
 */
import DictSelect from '@/components/DictSelect';
import TreeSelect from '@/components/TreeSelect';
import SchemaSelect from '@/components/SchemaSelect';
import AsyncSelect from '@/components/AsyncSelect';
import DictRadio from '@/components/DictRadio';
import { checkFormValue } from '@/utils/form';
import CitySelect from '@/components/CitySelect';
// import Coordinates from '@/components/Coordinates';
import CImgUploadNew from '@/components/Upload/CImgUploadNew';
import UploadFormItem from '@/components/Upload/UploadFormItem';
import CFileUpload from '@/components/Upload/CFileUploadList';
import CFileUploadList from '@/components/Upload/CFileUploadListNew';
import TreeCascade from '@/components/TreeCascade';
export default {
  name: 'FormItemGroup',
  components: {
    DictSelect,
    DictRadio,
    SchemaSelect,
    TreeSelect,
    CitySelect,
    CImgUploadNew,
    // Coordinates,
    UploadFormItem,
    CFileUpload,
    AsyncSelect,
    TreeCascade,
    CFileUploadList
  },
  inject: {
    selectOptionsGenerator: { value: 'selectOptionsGenerator', default: {} } // 修复console报错injection not found
  },
  props: {
    //列数据
    formData: {
      type: Object,
      required: true
    },
    labelWidth: {
      type: String,
      default: '90px',
      required: false
    }
  },
  data() {
    return {
      startCheck: false,
      editMode: 'edit'
    };
  },
  computed: {
    selectOptions() {
      if (!this.selectOptionsGenerator) return {};

      return this.selectOptionsGenerator();
    }
  },
  created() {},
  watch: {
    formData: {
      handler(newval, oldval) {}
    },
    deep: true
  },
  methods: {
    change(value, row = {}, prop = null) {
      this.$forceUpdate(); //强制刷新
      if (prop) {
        this.$emit('change', {
          value: value,
          prop: prop,
          childrenId: row.childrenId || null
        });
      } else {
        this.$emit('change', value, row, prop);
      }

      if (row && row.customChange) {
        if (row.type === 'select' && row.remote) {
          const list = row.condition
            ? this.selectOptions.$condition[prop] ||
              this.selectOptions[row.remote.list]
            : this.selectOptions[row.remote.list];
          row.customChange(
            this,
            value,
            list.find(i => i[row.remote.value] === value)
          );
        } else {
          row.customChange(this, value);
        }
      }
    },
    checkValue() {
      this.startCheck = true;

      for (let key in this.formData) {
        this.$set(this.formData[key], 'customError', '');
        // this.formData[key].customError = ''
      }

      this.$forceUpdate();

      return checkFormValue(this.formData);
    },
    onSingleImgUpload(key, res) {
      if (res && res.fileUrl) {
        this.$set(this.formData[key], 'value', res.fileUrl);
      }
    },
    onSingleImgRemove(key) {
      this.$set(this.formData[key], 'value', '');
    },
    onImgListUpload(key, res) {
      if (res && res.fileUrl) {
        this.$set(
          this.formData[key],
          'value',
          this.formData[key].value
            ? this.formData[key].value + ',' + res.fileUrl
            : res.fileUrl
        );
        this.$set(
          this.formData[key],
          'id',
          this.formData[key].id ? this.formData[key].id + ',' + res.id : res.id
        );
      }
    },
    onImgListRemove(key, index) {
      console.log('dd');
      let arr = (this.formData[key].value || '').split(',');
      let idArr = (this.formData[key].id || '').split(',');

      arr.splice(index, 1);
      idArr.splice(index, 1);

      this.$set(this.formData[key], 'value', arr.filter(i => i).join(','));
      this.$set(this.formData[key], 'id', idArr.filter(i => i).join(','));
    },
    renderUpdate() {
      this.$forceUpdate();
    },
    onVisibleChange(vis, row, prop) {
      console.log(123);
      if (vis) {
        if (row.condition) {
          this.$set(
            this.selectOptions.$condition,
            prop,
            this.selectOptions[row.remote.list].filter(i =>
              row.condition(i, this.formData)
            )
          );
        }
      }
    }
  }
};
</script>

<style scoped lang="scss">
::v-deep .el-form-item__content {
  width: calc(100% - var(--label-width));
}

::v-deep .form-item.hide-label .el-form-item__content {
  width: 100%;
}

.form-item-explain {
  font-size: 12px;
  line-height: 22px;
  opacity: 0.7;
}

.el-theme1 .el-form--inline .el-form-item {
  margin-right: 0;
}

.el-theme2 .el-form--inline .el-form-item {
  margin-right: 0;
}

.el-theme1 .el-cascader--small {
  width: 100%;
}

.el-theme2 .el-cascader--small {
  width: 100%;
}

.el-theme1 .el-date-editor.el-input,
.el-theme1 .el-date-editor.el-input__inner {
  width: 100%;
}

.el-theme1 .el-select,
.el-theme2 .el-select {
  width: 100%;
}

.el-theme1 .el-input-number--small,
.el-theme2 .el-input-number--small {
  width: 100%;
}

.el-theme2 .el-date-editor.el-input,
.el-theme2 .el-date-editor.el-input__inner {
  width: 100%;
}

::v-deep.singleImgUpload.upload-con {
  background: transparent;
  border: none;
  height: auto;
  min-height: auto;
  .el-upload {
    // border: 1px dashed rgb(204, 204, 204);
  }
}
::v-deep.imgListUpload.upload-con {
  background: transparent;
  height: auto;
  min-height: auto;
  border: none;
  .el-upload {
    // border: 1px dashed rgb(204, 204, 204);
  }
}

.custom-divider {
  ::v-deep.el-divider.el-divider--horizontal {
    width: calc(100% + var(--label-width));
  }
}
</style>
<style>
.el-theme1 .el-input.is-disabled .el-input__inner,
.el-theme1 .el-textarea.is-disabled .el-textarea__inner {
  /* color: #aaa; */
  color: #606266;
}

.el-theme2 .el-input.is-disabled .el-input__inner,
.el-theme2 .el-textarea.is-disabled .el-textarea__inner {
  /* color: #aaa; */
  color: #606266;
}

.el-theme1 .el-form-item--small .el-form-item__label {
  text-align: left;
}

.label-painter {
  margin-left: 13px;
}
/* .el-theme1 .el-cascader--small.is-disabled  {
  color: #606266 !important;
} */
.el-theme1 .el-cascader.is-disabled .el-input__inner::placeholder {
  color: #606266;
}

.el-theme1 .el-input-number .el-input__inner {
  text-align: left;
}
</style>
